/* global window */
/* global document */
import React, {Fragment} from 'react'
import NProgress from 'nprogress'
import PropTypes from 'prop-types'
import pathToRegexp from 'path-to-regexp'
import {EnumRoleType} from 'enums'
import {connect} from 'dva'
import GlobalFooter from 'components/GlobalFooter'
import {Loader, MyLayout} from 'components'
import {BackTop, Button, Dropdown, Icon, Layout, Menu, message, Tabs} from 'antd'
import {classnames, config, queryArray} from 'utils'
import {Helmet} from 'react-helmet'
import {withRouter} from 'dva/router'
import '../themes/index.less'
import './app.less'

const {Content, Sider} = Layout
const {Header, styles} = MyLayout
const {prefix, openPages, footer} = config
const TabPane = Tabs.TabPane

let lastHref

function noBack () {
  history.pushState(null, null, document.URL)
}

const App = ({
               children, dispatch, app, loading, location,
             }) => {

  const {iconFontJS, iconFontCSS, logo, whitelist} = config
  const {
    user, siderFold, darkTheme, destroyed, isNavbar, menuPopoverVisible, navOpenKeys, menu, panes, activeKey,
  } = app
  const {permissions} = user
  let {pathname, query} = location
  if (pathname) {
    pathname = pathname.startsWith('/') ? pathname : `/${pathname}`
  }
  const current = app.menu.filter(item => pathToRegexp(item.route || '').exec(pathname))
  const hasPermission = current.length ? app.permissions.visit.includes(current[0].id) : false
  if (!whitelist.includes(pathname) && app.permissions.role !== EnumRoleType.ADMIN && permissions && !hasPermission) {
    console.warn("[access denied] you don't have access permission")
    location.pathname = "/403"
    const curTab = queryArray(panes, activeKey)
    if (curTab) {
      curTab.content = children
    }
  }

  if (pathname === '/login') {
    noBack()
    addEventListener('popstate', noBack)
  } else {
    removeEventListener('popstate', noBack)
  }

  const {href} = window.location

  if (lastHref !== href) {
    NProgress.start()
    if (!loading.global) {
      NProgress.done()
      lastHref = href
    }
  }

  const modelAction = (action, payload) => {
    dispatch({
      type: `app/${action}`,
      payload,
    })
  }

  const headerProps = {
    menu,
    user,
    activeKey,
    siderFold,
    isNavbar,
    menuPopoverVisible,
    navOpenKeys,
    switchMenuPopover () {
      modelAction('switchMenuPopver')
    },
    logout () {
      modelAction('logout')
    },
    switchSider () {
      modelAction('switchSider')
    },
    changeOpenKeys (openKeys) {
      modelAction('handleNavOpenKeys', {navOpenKeys: openKeys})
    },
  }

  // ========================================== Tab start ==========================================

  const operationMenu = (
    <Menu onClick={e => {
      if (e.key === "1") {
        closeOther()
      } else {
        closeAll()
      }
    }}>
      <Menu.Item key="1">关闭其他</Menu.Item>
      <Menu.Item key="2">关闭所有</Menu.Item>
    </Menu>
  )

  const operations =
    (<Dropdown overlay={operationMenu}>
      <Button style={{marginLeft: 8}}>操作 <Icon type="down"/></Button>
    </Dropdown>)

  const closeOther = () => {
    if (panes.length === 1) {
      message.info("最后一个面板不能关闭哦")
    }

    modelAction('closeOtherTab')
  }
  const closeAll = () => {
    modelAction('closeAllTab')
    location.pathname = '/dashboard'
    setHistory('/dashboard')
  }

  const addTab = menu => {
    const {route} = menu
    const {props} = children
    const {location: loc} = props
    if (loc.pathname !== route) {
      location.pathname = route
      setHistory(route)
    }

    modelAction('addTab', {menu, children})
  }

  const handleTabChange = key => {
    let changed = false
    const tab = queryArray(panes, key)
    if (tab) {
      if (!tab.content) {
        location.pathname = tab.key
        changed = true
      } else {
        const {location: loc} = tab.content.props
        if (loc && loc.pathname !== tab.key) {
          location.pathname = tab.key
          changed = true
        }
      }
    }
    setHistory(key)

    modelAction('changeTab', {
      changed,
      key,
      children,
    })
  }

  const setHistory = key => {
    history.pushState({}, "", key)
  }

  const closeTab = (key) => {
    modelAction('closeTab', {key})
  }

  if (pathname === '/login' && query) {
    if (query.destroy && !destroyed) {
      modelAction('destroy')
    }
  }

  // ========================================== Tab end ==========================================

  const siderProps = {
    menu,
    siderFold,
    darkTheme,
    navOpenKeys,
    handleMenuClick (menu) {
      addTab(menu)
    },
    activeKey,
    changeTheme () {
      modelAction('switchTheme')
    },
    changeOpenKeys (openKeys) {
      window.localStorage.setItem(`${prefix}navOpenKeys`, JSON.stringify(openKeys))
      modelAction('handleNavOpenKeys', {navOpenKeys: openKeys})
    },
  }

  if (openPages && openPages.includes(pathname)) {
    return (<div>
      <Loader fullScreen spinning={loading.effects['app/query']}/>
      {children}
    </div>)
  }

  const getTabIcon = key => {
    return panes.length > 1 ? <Icon type="close" onClick={() => {
      window.clossetab = key
      closeTab(key)
    }}/> : ''
  }

  const getContent = pane => {
    if (pane.content) {
      return pane.content
    } else {
      location.pathname = pane.key
      pane.content = children
      return children
    }
  }

  return (
    <div>
      <Loader fullScreen spinning={loading.effects['app/query']}/>
      <Helmet>
        <title>微服云平台-为微信服务商打造最全面的一站式解决方案</title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
        <link rel="icon" href={logo} type="image/x-icon"/>
        {iconFontJS && <script src={iconFontJS}/>}

        {iconFontCSS && <link rel="stylesheet" href={iconFontCSS}/>}
      </Helmet>

      <Layout className={classnames({[styles.dark]: darkTheme, [styles.light]: !darkTheme})}>
        {!isNavbar && <Sider
          trigger={null}
          // collapsible
          collapsed={siderFold}
          width={220}
        >
          {siderProps.menu.length === 0 ? null : <MyLayout.Sider {...siderProps} />}
        </Sider>}
        <Layout style={{height: '100vh', overflow: 'scroll'}} id="mainContainer">
          <BackTop target={() => document.getElementById('mainContainer')}/>
          <Header {...headerProps} />
          <Content>
            {panes ? <Tabs activeKey={activeKey} onChange={handleTabChange} tabBarExtraContent={operations}>
              {panes.map(pane => {
                return (<TabPane tab={(
                  <div>{pane.title} {getTabIcon(pane.key)}</div>)}
                                 key={pane.key}>
                  {getContent(pane)}
                </TabPane>)
              })}
            </Tabs> : ""}
            <GlobalFooter links={footer.links}
                          copyright={<Fragment>Copyright <Icon type="copyright"/> {footer.copyright}</Fragment>}/>
          </Content>
        </Layout>
      </Layout>
    </div>
  )
}

App.propTypes = {
  children: PropTypes.element.isRequired,
  location: PropTypes.object,
  dispatch: PropTypes.func,
  app: PropTypes.object,
  loading: PropTypes.object,
}

export default withRouter(connect(({app, loading}) => ({app, loading}))(App))
